﻿using System;
using System.Collections.Generic;
using System.DirectoryServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Management;

namespace ImbedLibrary
{
    public class UserHelper
    {

        private static readonly string path = "WinNT://" + Environment.MachineName;

        /// <summary>
        /// 删除用户
        /// </summary>
        /// <param name="userName">用户名</param>
        /// <returns></returns>
        public static string RemoveUser(string userName)
        {
            try
            {
                using (DirectoryEntry dir = new DirectoryEntry(path))
                {
                    DirectoryEntry user = null;
                    user = dir.Children.Find(userName, "user");
                    if (user != null)
                    {
                        dir.Children.Remove(user);
                        return "ok";
                    }
                    Logs.Note("没有找到用户");
                    return "没找到用户";
                }
            }
            catch (Exception)
            {

                throw;
            }

        }

        /// <summary>
        /// 启用或禁用windows用户
        /// </summary>
        /// <param name="userName">用户名</param>
        /// <param name="isDisable">状态</param>
        public static void Disable(string userName,bool isDisable)
        {
            using (DirectoryEntry dir = new DirectoryEntry(path))
            {
                DirectoryEntry user = dir.Children.Find(userName, "user");
                if (userName.ToLower() == "guest")
                {
                    user.InvokeSet("AccountDisabled", true);

                }
                else
                {
                    if (Convert.ToBoolean(user.InvokeGet("AccountDisabled")) != isDisable)
                    {
                        user.InvokeSet("AccountDisabled", isDisable);
                    }
                }
                user.CommitChanges();
            }
        }

        /// <summary>
        /// 获取所有的windows用户名
        /// </summary>
        /// <returns></returns>
        public static List<string> GetAllUser()
        {
            List<string> users = new List<string>();
            SelectQuery query = new SelectQuery("Win32_UserAccount");
            ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
            foreach (var envVar in searcher.Get())
            {
                Console.WriteLine("UserName: {0}",envVar["Name"]);
                users.Add(envVar["Name"].ToString());
            }
            return users;
        }

        /// <summary>
        /// 获取所有的windows用户名
        /// </summary>
        public static List<string> GetGroupUser()
        {
            List<String> users = new List<string>();//所有的用户名
            unsafe
            {
                LOCALGROUP_INFO_1_SIZE = sizeof(Win32API.LOCALGROUP_INFO_1);
                LOCALGROUP_MEMBERS_INFO_1_SIZE = sizeof(Win32API.LOCALGROUP_MEMBERS_INFO_1);
            }
            uint level = 1, prefmaxlen = 0xFFFFFFFF, entriesread = 0, totalentries = 0;

            IntPtr groupInfoPtr, userInfoPtr;
            groupInfoPtr = IntPtr.Zero;
            userInfoPtr = IntPtr.Zero;

            Win32API.NetLocalGroupEnum(IntPtr.Zero, level, ref groupInfoPtr, prefmaxlen, ref entriesread, ref totalentries, IntPtr.Zero);

            commentArray = new string[totalentries];

            for (int i = 0; i < totalentries; i++)
            {
                int newOffset = groupInfoPtr.ToInt32() + LOCALGROUP_INFO_1_SIZE * i;
                Win32API.LOCALGROUP_INFO_1 groupInfo = (Win32API.LOCALGROUP_INFO_1)Marshal.PtrToStructure(new IntPtr(newOffset), typeof(Win32API.LOCALGROUP_INFO_1));
                string currentGroupName = Marshal.PtrToStringAuto(groupInfo.lpszGroupName);
                commentArray[i] = Marshal.PtrToStringAuto(groupInfo.lpszComment);
                uint prefmaxlen1 = 0xFFFFFFFF, entriesread1 = 0, totalentries1 = 0;

                Win32API.NetLocalGroupGetMembers(IntPtr.Zero, groupInfo.lpszGroupName, 1, ref userInfoPtr, prefmaxlen1, ref entriesread1, ref totalentries1, IntPtr.Zero);
                for (int j = 0; j < totalentries1; j++)
                {
                    int newOffset1 = userInfoPtr.ToInt32() + LOCALGROUP_MEMBERS_INFO_1_SIZE * j;
                    Win32API.LOCALGROUP_MEMBERS_INFO_1 memberInfo = (Win32API.LOCALGROUP_MEMBERS_INFO_1)Marshal.PtrToStructure(new IntPtr(newOffset1), typeof(Win32API.LOCALGROUP_MEMBERS_INFO_1));
                    string currentUserName = Marshal.PtrToStringAuto(memberInfo.lgrmi1_name);
                    if(!users.Exists(u => u.ToString() == currentUserName))
                    { 
                        users.Add(currentUserName);
                    }
                }
                Win32API.NetApiBufferFree(userInfoPtr);
            }
            Win32API.NetApiBufferFree(groupInfoPtr);
            return users;
        }

        private static int LOCALGROUP_MEMBERS_INFO_1_SIZE;

        private static int LOCALGROUP_INFO_1_SIZE;

        private static string[] commentArray;

        /// <summary>
        /// 获取结构
        /// </summary>
        /// <returns></returns>
        public static DirectoryEntry GetEnt()
        {
            return new DirectoryEntry(path);
        }

        /// <summary>
        /// 用户是否存在
        /// </summary>
        /// <param name="userName">用户名</param>
        /// <returns>存在[true]不存在[false]</returns>
        public static Boolean Exists(String userName)
        {
            using (DirectoryEntry ent = GetEnt())
            {
                DirectoryEntry user = null;
                try
                {
                    user = ent.Children.Find(userName, "user");
                    return true;
                }
                catch (Exception)
                {
                    return false;
                }
            }
        }

        /// <summary>
        /// 创建站点用户
        /// </summary>
        /// <returns></returns>
        public static Boolean CreateWebSite()
        {
            String user = "WebSite";
            String password = "WebSite!QAZ1qaz";
            String meg = String.Empty;
            if (!Exists(user))
            {
                meg = CreateUser(user, password, "网站访问用户");
                if (meg == "ok") { return true; }
                else { return false; }
            }
            return false;
        }

        /// <summary>
        /// 创建用户
        /// </summary>
        /// <returns>结果[true|false,密码]</returns>
        public static String[] CreateUser(String userName, String describe)
        {
            String[] result = {"false",userName,""};
            Random rd = new Random();
            string str = @"0123456789abcdefghigklmnopqrstuvwxyzABCDEFGHIGKLMNOPQRSTUVWXYZ";
            String pwd = String.Empty;
            for (int i = 0; i < 21; i++)
            {
                pwd += str.Substring(0 + rd.Next(61), 1);
            }
            result[2] = pwd;
            if (CreateUser(userName, result[2], describe) == "ok")
            { result[0] = "true"; }
            else
            {
                return CreateUser(userName + "01", describe);
            } 
            return result;
        }

        /// <summary>
        /// CreateUser
        /// </summary>
        /// <param name="userName">用户名</param>
        /// <param name="userPassword">密码</param>
        /// <param name="describe">描述</param>
        /// <returns></returns>
        public static string CreateUser(string userName, string userPassword, string describe)
        {
            using (DirectoryEntry dir = new DirectoryEntry(path))
            {
                DirectoryEntry user = null;
                try
                {
                    user = dir.Children.Find(userName, "user");
                }
                catch (Exception)
                { }
                if (user == null)
                {
                    user = dir.Children.Add(userName, "user");
                    user.Invoke("SetPassword", new object[] { userPassword });
                    user.CommitChanges();

                    user.Invoke("Put", new object[] { "Description", describe });
                    user.Invoke("Put", new object[] { "UserFlags", 0x0040 | 66049 });
                    user.CommitChanges();

                    dir.Close();
                    return "ok";
                }
                else
                {
                    string meg = "已存在用户：" + userName;
                    Logs.Note(meg);
                    return meg;
                }
            }
        }
    }
}
